package codeGenerator;


import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.LikeTable;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import org.apache.ibatis.annotations.Mapper;

import java.util.Collections;
import java.util.Scanner;

/**
 * @author chub
 * @describe resources目录下的templates目录下有两个模板文件controller.java.ftl、entity.java.ftl
 * 这里需要mybatis-plus-generator 3.5.6版本
 */
public class FastAutoGeneratorFreemarker {

    static String URL = "jdbc:mysql://localhost:3306/chubtest?useUnicode=true&characterEncoding=utf8&useSSL=false";
    static String DRIVER = "com.mysql.cj.jdbc.Driver";
    static String USERNAME = "root";
    static String PASSWORD = "root";

    //指定要映射的数据库表，可以写多个，用逗号分开
    static String tables = "t_bank_card_bin_inf";


    // 项目路径
    public static String projectPath = System.getProperty("user.dir");
    // projectPath = D:\develop\Projects-Idea\springStudy


    /**
     * 指定具体项目模块
     */
    public static String MOUDLE_NAME = "springbootStudy/springbootstudy-mybatis/";
    public static String MOUDLE_PATH = projectPath + "/springbootStudy/springbootstudy-mybatis/";
    public static String AUTHOR_NAME = "chub";

    /**
     * 路径设置
     */
    public static String MOUDLE_SRC_PATH = MOUDLE_PATH + "src/test/";
    public static String JAVA_ROOT_PATH = MOUDLE_SRC_PATH + "java/";
    public static String JAVA_PATH = JAVA_ROOT_PATH + "/com/chub/study/modules/";
    public static String RESOURCES_ROOT_PATH = MOUDLE_SRC_PATH + "resources/";
    public static String MAPPER_PATH = RESOURCES_ROOT_PATH + "mapper/";

    /**
     * DTO/VO/QueryDTO 包路径，这里根据实际情况设置DTO\VO\ENTITY的路径
     */
    // DO：对应数据库表结构
    // VO：一般用于前端展示用
    // DTO：用于数据传递（接口入参和接口返回值都可以）
    public static String ENTITY_PATH = JAVA_PATH + "entity/";
    public static String VO_PATH = JAVA_PATH + "entity/";
    public static String DTO_PATH = JAVA_PATH + "entity/";


    public static String MOUDLE_PACKAGE = "com.chub.study.modules";
    public static String BASE_PACKAGE = MOUDLE_PACKAGE + ".base";
    /**
     * DTO/VO/QueryDTO 包名
     */
    public static String ENTITY_PACKAGE = MOUDLE_PACKAGE + ".entity";
    public static String DTO_PACKAGE = MOUDLE_PACKAGE + ".entity";
    public static String VO_PACKAGE = MOUDLE_PACKAGE + ".entity";
    // public static String PARENT_Query_DTO_PACKAGE = PARENT_PACKAGE + ".dto";
    /**
     * DTO/VO/QueryDTO 自定义模板路径
     * <p>
     * 这里定义DTO是请求参数类， VO是响应数据类
     */
    public static String TEMPLATE_CONTROLLER_PATH = "/vm/java/swagger2/controller.java";
    public static String TEMPLATE_SERVICE_PATH = "/vm/java/swagger2/service.java";
    public static String TEMPLATE_SERVICEIMPL_PATH = "/vm/java/swagger2/serviceImpl.java";
    public static String TEMPLATE_MAPPER_PATH = "/vm/java/swagger2/mapper.java";
    public static String TEMPLATE_MAPPER_XML_PATH = "/vm/xml/mapper.xml.vm";
    /**
     * DTO/VO/QueryDTO 自定义模板路径
     */
    public static String TEMPLATE_DTO_PATH = "/vm/java/swagger2/dto.java.vm";
    public static String TEMPLATE_ENTITY_PATH = "/vm/java/swagger2/entity.java.vm";
    public static String TEMPLATE_VO_PATH = "/vm/java/swagger2/vo.java.vm";
    // public static String TEMPLATE_QUERY_DTO_PATH = "/vm/java/queryDto.java.vm";


    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }

    public static void main(String[] args) {

        FastAutoGenerator.create(URL, USERNAME, PASSWORD)
                // 数据库配置 & DataSourceConfig
                // url jdbc路径
                // username 数据库账号
                // password 数据库密码
                // .dataSourceConfig()

                // 全局配置 & GlobalConfig
                // disableOpenDir 禁止打开输出目录 默认值:true
                // outputDir(String) 指定输出目录 /opt/baomidou/ 默认值: windows:D:// linux or mac : /tmp
                // author(String) 作者名 baomidou 默认值:作者
                // enableKotlin 开启 kotlin 模式 默认值:false
                // enableSwagger 开启 swagger 模式 默认值:false
                // dateType(DateType) 时间策略 DateType.ONLY_DATE 默认值: DateType.TIME_PACK
                // commentDate(String) 注释日期 默认值: yyyy-MM-dd
                .globalConfig(builder -> {
                    builder.outputDir(JAVA_ROOT_PATH)     //指定输出的位置
                            .author("Chub")   //修改1 谁的模块用谁的名字
                            .disableOpenDir()    //是否打开资源管理器
                            .enableSwagger()
                            .commentDate("yyyy-MM-dd")
                            .dateType(DateType.TIME_PACK) //设置日期生成策略
                            .build();
                })
                // 包配置 & PackageConfig
                // parent(String) 父包名 默认值:com.baomidou
                // moduleName(String) 父包模块名 默认值:无
                // entity(String) Entity 包名 默认值:entity
                // service(String) Service 包名 默认值:service
                // serviceImpl(String) Service Impl 包名 默认值:service.impl
                // mapper(String) Mapper 包名 默认值:mapper
                // xml(String) Mapper XML 包名 默认值:mapper.xml
                // controller(String) Controller 包名 默认值:controller
                // other(String) 自定义文件包名 输出自定义文件时所用到的包名
                // pathInfo(Map<OutputFile, String>) 路径配置信息 Collections.singletonMap(OutputFile.mapperXml, "D://")
                .packageConfig(builder -> {
                    builder.parent(MOUDLE_PACKAGE)
                            .moduleName("")
                            .entity("entity")
                            .service("service")
                            .serviceImpl("service.impl")
                            .mapper("mapper")
                            // .xml("mapper.xml")  // 这样将在mapper目录下再建一个xml目录
                            .controller("controller")
                            .pathInfo(Collections.singletonMap(OutputFile.xml, MAPPER_PATH))  // 这里可以生成指定的目录
                            .build();
                })
                // 模板配置 & TemplateConfig
                // disable 禁用所有模板
                // disable(TemplateType...) 禁用模板,比如实体模版 TemplateType.ENTITY
                // entity(String) 设置实体模板路径(JAVA) /templates/entity.java
                // entityKt(String) 设置实体模板路径(kotlin) /templates/entity.java
                // service(String) 设置 service 模板路径 /templates/service.java
                // serviceImpl(String) 设置 serviceImpl 模板路径 /templates/serviceImpl.java
                // mapper(String) 设置 mapper 模板路径 /templates/mapper.java
                // controller(String) 设置 controller 模板路径 /templates/controller.java
                // .templateConfig(builder -> {
                //     builder.disable(TemplateType.ENTITY)
                //             .controller("/templates/controller.java")  // 设置 controller 模板路径 /templates/controller.java
                //             .entity("/templates/entity.java")  // 设置实体模板路径(JAVA) /templates/entity.java
                //             .xml(null)
                //             .build();
                // })
                //  VelocityTemplateEngine  FreemarkerTemplateEngine BeetlTemplateEngine EnjoyTemplateEngine
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                // .templateEngine(new FreemarkerTemplateEngine())
                .templateEngine(new FreemarkerTemplateEngine())
                // 注入配置

                // 策略配置 & StrategyConfig
                // enableCapitalMode 开启大写命名 默认值:false
                // enableSkipView 开启跳过视图 默认值:false
                // disableSqlFilter 禁用 sql 过滤 默认值:true，语法不能支持使用 sql 过滤表的话，可以考虑关闭此开关
                // enableSchema 启用 schema 默认值:false，多 schema 场景的时候打开
                // likeTable(LikeTable) 模糊表匹配(sql 过滤) likeTable 与 notLikeTable 只能配置一项
                // notLikeTable(LikeTable) 模糊表排除(sql 过滤) likeTable 与 notLikeTable 只能配置一项
                // addInclude(String...) 增加表匹配(内存过滤) include 与 exclude 只能配置一项 ，支持正则匹配、例如 ^t_.* 所有 t_ 开头的表名
                // addExclude(String...) 增加表排除匹配(内存过滤) include 与 exclude 只能配置一项 ，支持正则匹配、例如 .*st$ 所有 st 结尾的表名
                // addTablePrefix(String...) 增加过滤表前缀
                // addTableSuffix(String...) 增加过滤表后缀
                // addFieldPrefix(String...) 增加过滤字段前缀
                // addFieldSuffix(String...) 增加过滤字段后缀
                // outputFile 内置模板输出文件处理
                // entityBuilder 实体策略配置
                // controllerBuilder controller 策略配置
                // mapperBuilder mapper 策略配置
                // serviceBuilder service 策略配置
                .strategyConfig(builder -> {
                    builder.enableCapitalMode()
                            .enableSkipView()
                            .disableSqlFilter()
                            .likeTable(new LikeTable(tables))
                            .addInclude(tables)
                            .addTablePrefix("t_", "c_")
                            .addFieldSuffix("_flag").addInclude("sys...ion") // 设置需要生成的数据表名
                            .addTablePrefix("t_", "c_") // 设置过滤表前缀
                            //4.1、Mapper策略配置
                            .mapperBuilder()
                            .enableFileOverride() // 覆盖已生成文件
                            .superClass(BaseMapper.class)   //设置父类
                            .formatMapperFileName("%sMapper")   //格式化 mapper 文件名称
                            // .enableMapperAnnotation()       //开启 @Mapper 注解
                            .mapperAnnotation(Mapper.class)    // 和“enableMapperAnnotation”一样的效果
                            // .mapperXmlTemplate()
                            //4.2、service 策略配置
                            .serviceBuilder()
                            .superServiceImplClass("com.baomidou.mybatisplus.extension.service.impl.ServiceImpl")
                            .superServiceClass("com.baomidou.mybatisplus.extension.service.IService")
                            .formatServiceFileName("%sService") //格式化 service 接口文件名称，%s进行匹配表名，如 UserService
                            .formatServiceImplFileName("%sServiceImpl") //格式化 service 实现类文件名称，%s进行匹配表名，如 UserServiceImpl
                            //4.3、实体类策略配置
                            .entityBuilder()
                            .enableLombok() //开启 Lombok
                            .disableSerialVersionUID()  //不实现 Serializable 接口，不生产 SerialVersionUID
                            .logicDeleteColumnName("deleted")   //逻辑删除字段名
                            .naming(NamingStrategy.underline_to_camel)  //数据库表映射到实体命名策略：下划线转驼峰命的
                            .columnNaming(NamingStrategy.underline_to_camel)    //数据库表字段映射到实体的命名策略：下划线转驼峰命
                            .enableFileOverride()
                            .addTableFills(
                                    new Column("create_time", FieldFill.INSERT),
                                    new Column("modify_time", FieldFill.INSERT_UPDATE)
                            )   //添加表字段填充，"create_time"字段自动填充为插入时间，"modify_time"字段自动填充为插入修改时间
                            .enableTableFieldAnnotation()       // 开启生成实体时生成字段注解
                            // .javaTemplate("/templates/entity.java")  // 不知道是否有用 TODO
                            //4.4、Controller策略配置
                            .controllerBuilder()
                            .formatFileName("%sController") //格式化 Controller 类文件名称，%s进行匹配表名，如 UserController
                            .enableFileOverride() // 覆盖已生成文件
                            .enableRestStyle()  //开启生成 @RestController 控制器
                            // .template("/templates/controller.java")  // 不知道是否有用 TODO
                            .build();
                })
                .execute();

    }

}
